﻿using System.Collections.Generic;
using System.Linq;

using Microsoft.Phone.Controls;

using NavigationCoercion.Patterns;

namespace NavigationCoercion
{
    /*
     * Usage example:
        
        var fluent = new FluentNavigation(RootFrame);
            
        fluent.WhenNavigatedTo<MainPage>()
                .ThenTo<LoginPage>()
                .ThenToAnyPage()
                .RemoveEntriesFromBackStack(1);

        fluent.WhenNavigatedTo<MainPage>()
                .ThenTo<LoginPage>()
                .ThenTo<RegisterPage>()
                .ThenTo<PaymentPage>()
                .RemoveEntriesFromBackStackTill<MainPage>();

        fluent.WhenNavigatedTo<MainPage>()
                .ThenTo<SecondPage>()
                .ThenTo<RegisterPage>()
                .ThenOptionallyTo<ForgotPasswordPage>()
                .ThenToAnyPage()
                .RemoveEntriesFromBackStackTill<MainPage>();

        fluent.WhenNavigatingTo<PaymentPage>()
                .RedirectTo<LoginPage>();

        fluent.WhenNavigatingTo<PaymentPage>()
                .If(() => false)
                .RedirectWithReturnUri<LoginPage>("ReturnUri");     
     */
    public class FluentNavigation
    {
        private readonly PhoneApplicationFrame frame;
        private readonly List<INavigatingPattern> _navigatingActions = new List<INavigatingPattern>();
        private readonly List<INavigatedPattern> _navigatedActions = new List<INavigatedPattern>();

        public FluentNavigation(PhoneApplicationFrame frame)
        {
            this.frame = frame;
            this.frame.Navigated += this.OnNavigated;
            this.frame.Navigating += this.OnNavigating;
        }

        public INavigatedPattern WhenNavigatedTo<T>()
        {
            var action = new NavigatedPattern(typeof(T));

            _navigatedActions.Add(action);

            return action;
        }

        public INavigatingPattern WhenNavigatingTo<T>()
        {
            var action = new NavigatingPattern(typeof(T));

            _navigatingActions.Add(action);

            return action;
        }

        private void OnNavigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            foreach (var action in _navigatingActions.Cast<NavigatingPattern>())
            {
                if (action.TryApply(e, frame)) 
                    break;
            }
        }

        private void OnNavigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            foreach (var action in _navigatedActions.Cast<NavigatedPattern>())
            {
                if (action.TryApply(e, frame)) 
                    break;
            }
        }
    }
}